'use strict';
const State = require("../lib/state.com");
const { RUN_ACT, ROLL_ACT, JUMP_ACT, JUMP_END, ROLL_END } = require('../utils/const');

let evaluating = false;
let model;
let instance;

// 闭包函数，仅当message 相等时返回true
function on (message) {
    return function (msgToEvaluate) {
        return msgToEvaluate === message;
    }
}

const exports = {
  init: function (target) {
    State.setConsole(console);
    model = new State.StateMachine("action");
    const initial = new State.PseudoState("init-action", model, State.PseudoStateKind.Initial);
    // running state
    const run = new State.State(RUN_ACT, model);
    // jump state
    const jump = new State.State(JUMP_ACT, model);
    // roll state
    const roll = new State.State(ROLL_ACT, model);
    const jumpEnd = new State.State(JUMP_END, model);
    const rollEnd = new State.State(ROLL_END, model);
    // target hook
    // enter run
    run.entry( function () {
       target.onRunState(true);
    });
    // exit run
    run.exit(function () {
       target.onRunState(false);
    });
    // enter jump
    jump.entry( function () {
       target.onJumpState(true);
    });
    // exit jump
    jump.exit(function () {
       target.onJumpState(false);
    });
    // enter roll
    roll.entry( function () {
       target.onRollState(true);
    });
    // exit roll
    roll.exit(function () {
       target.onRollState(false);
    });

    // 状态机的转换
    // 初始状态
    initial.to(run);
    run.to(jump).when(on(JUMP_ACT));
    jump.to(jumpEnd).when(on(JUMP_END));
    jumpEnd.to(run).when(on(RUN_ACT));

    // roll
    run.to(roll).when(on(ROLL_ACT));
    roll.to(rollEnd).when(on(ROLL_END));
    rollEnd.to(run).when(on(RUN_ACT));
    instance = new State.StateMachineInstance("fsm");
    State.initialise(model, instance);
  },
  toRun: function () {
      this._evaluate(RUN_ACT);
    },
  toJump: function() {
      this._evaluate(JUMP_ACT);
  },
  toRoll: function() {
      this._evaluate(ROLL_ACT);
  },
  toRollEnd: function() {
      this._evaluate(ROLL_END);
  },
  toJumpEnd: function() {
      this._evaluate(JUMP_END);
  },
  _evaluate: function (message) {
      if (evaluating) {
          // can not call fsm's evaluate recursively
          setTimeout(function () {
              State.evaluate(model, instance, message);
          }, 2);
          return;
      }
      evaluating = true;
      State.evaluate(model, instance, message);
      evaluating = false;
  },
};

module.exports = exports;

// // example
// class Demo {
//     constructor() {
//         this.state = RUN_ACT;
//     }
//     onRunState(isEnter) {
//         if(isEnter) {
//             this.state = RUN_ACT;
//         }
//     }
//     onJumpState(isEnter) {
//         if(isEnter) {
//             this.state = JUMP_ACT;
//         }
//     }
//     onRollState(isEnter) {
//         if(isEnter) {
//             this.state = RUN_ACT;
//         }
//     }
//     printState() {
//         console.log(`current state is = ${this.state}\n`);
//     }
// }
// const fsm = exports;
// const target = new Demo();
// fsm.init(target);
// target.printState();
// fsm.toJump();
// target.printState();
// fsm.toRoll();
// target.printState();
// fsm.toRun();
// target.printState();